﻿namespace LogicStudio.Framework.UI.Comun
{
    using Controles;
    using System.Collections.Generic;
    using System.ServiceModel.DomainServices.Client;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System;
    using Utilidades;

    /// <summary>
    /// Clase abstracta genérica para la construcción de busquedas mediante el patrón de diseño vista modelos 
    /// </summary>
    /// <typeparam name="TContexto">
    /// Parámetro del tipo DomainContext (Servicio RIA)
    /// Que se utilizara como fuente de datos
    /// </typeparam>
    public abstract class BusquedaBase<TContexto> : ModeloFramework, IObjetoBusqueda
        where TContexto : DomainContext, new()
    {

        #region Constantes
        private const string PropiedadReset = "Reset";
        private const string PropiedadFiltro1 = "Filtro1";
        private const string PropiedadFiltro2 = "Filtro2";
        private const string PropiedadFiltro3 = "Filtro3";
        private const string PropiedadFiltro4 = "Filtro4";
        private const string PropiedadFiltro5 = "Filtro5";

        #endregion

        #region Atributos
        /// <summary>
        /// Comando fuente de Datos.
        /// </summary>
        private DomainDataSource _fuenteDatos;
        private TContexto _contexto;
        private ComandoBuscar _comandoBuscar;
        private bool _reset;

        #endregion

        #region Metodos Protegidos

        /// <summary>
        /// Representa la lista de filtros que se utiliza dentro de la búsqueda
        /// </summary>
        protected abstract List<FilterDescriptor> Filtros { get; }

        /// <summary>
        /// Representa el nombre del método de la consulta utilizado para la búsqueda
        /// </summary>
        protected abstract string NombreMetodoConsulta { get; }
        #endregion

        #region Propiedaded

        /// <summary>
        /// Instancia de contecto correspondiente al parámetro genérico
        /// </summary>
        public TContexto Contexto
        {
            get
            {
                if (_contexto == null)
                {
                    _contexto = new TContexto();
                }
                return _contexto;
            }
        }

        /// <summary>
        /// Propiedad que indica si se ha pulsado el botón Reset
        /// </summary>
        public bool Reset
        {
            get
            {
                if (_reset)
                    _reset = false;
                return _reset;
            }
            set
            {
                _reset = value;
                RaisePropertyChanged(PropiedadReset);
            }
        }
        /// <summary>
        /// Propiedades que se utiliza para realizar filtros
        /// </summary>
        private string _filtro1;
        public string Filtro1
        {
            get
            {
                if (Reset)
                {
                    _filtro1 = null;
                }
                return _filtro1;
            }
            set
            {
                if (_filtro1 == value)
                {
                    return;
                }

                _filtro1 = value;
                RaisePropertyChanged(PropiedadFiltro1);
            }
        }
        private string _filtro2;
        public string Filtro2
        {
            get
            {
                if (Reset)
                {
                    _filtro2 = null;
                }
                return _filtro2;
            }
            set
            {
                if (_filtro2 == value)
                {
                    return;
                }

                _filtro2 = value;
                RaisePropertyChanged(PropiedadFiltro2);
            }
        }

        private string _filtro3;
        public string Filtro3
        {
            get
            {
                if (Reset)
                {
                    _filtro3 = null;
                }
                return _filtro3;
            }
            set
            {
                if (_filtro3 == value)
                {
                    return;
                }

                _filtro3 = value;
                RaisePropertyChanged(PropiedadFiltro3);
            }
        }

        private string _filtro4;
        public string Filtro4
        {
            get
            {
                if (Reset)
                {
                    _filtro4 = null;
                }
                return _filtro4;
            }
            set
            {
                if (_filtro4 == value)
                {
                    return;
                }

                _filtro4 = value;
                RaisePropertyChanged(PropiedadFiltro4);
            }
        }

        private string _filtro5;
        public string Filtro5
        {
            get
            {
                if (Reset)
                {
                    _filtro5 = null;
                }
                return _filtro5;
            }
            set
            {
                if (_filtro5 == value)
                {
                    return;
                }

                _filtro5 = value;
                RaisePropertyChanged(PropiedadFiltro5);
            }
        }

        /// <summary>
        /// Comando utilizado cuando se realiza la busqueda o se resetea
        /// </summary>
        public ComandoBuscar ComandoBuscar
        {
            get { return _comandoBuscar ?? (_comandoBuscar = new ComandoBuscar(this)); }
        }

        /// <summary>
        /// Propiedad que controla la fuente de acceso a datos
        /// </summary>
        public DomainDataSource FuenteDatos
        {
            get
            {
                if (_fuenteDatos == null)
                {
                    var recurso = LogicStudio.Framework.UI.Utilidades.RecursosLenguaje.Recursos;
                    _fuenteDatos = new DomainDataSource();
                    _fuenteDatos.DomainContext = Contexto;
                    _fuenteDatos.PageSize = Convert.ToInt32(recurso.GetType().GetProperty("TotalBusqueda").GetValue(_fuenteDatos.PageSize, null));
                    _fuenteDatos.QueryName = NombreMetodoConsulta;
                    _fuenteDatos.FilterDescriptors.Clear();
                    _fuenteDatos.LoadedData += ClientDataSourceLoaded;
                }
                else
                {
                    if (Filtros != null || _reset)
                    {
                        _fuenteDatos.FilterDescriptors.Clear();
                        foreach (var item in Filtros)
                        {
                            if (item.Value != null)
                            {
                                _fuenteDatos.FilterDescriptors.Add(item);
                            }
                        }
                    }
                }
                return _fuenteDatos;
            }
            set
            {
                _fuenteDatos = value;
            }
        }
        #endregion

        #region IObjetoBusqueda

        public virtual void AplicarBusqueda()
        {
            Reset = false;
            FuenteDatos.SortDescriptors.Clear();
            FuenteDatos.Load();
        }

        public virtual void AplicarReset()
        {
            Reset = true;
            Filtro1 = string.Empty;
            Filtro2 = string.Empty;
            Filtro3 = string.Empty;
            Filtro4 = string.Empty;
            Filtro5 = string.Empty;
            FuenteDatos.SortDescriptors.Clear();
            FuenteDatos.Load();
        }

        #endregion

        #region Métodos Privados

        /// <summary>
        /// Método privado estático que se ejecuta como CallBack al invocar al método Load de la Fuente de Datos
        /// </summary>
        /// <param name="sender">Propiedad global FuenteDatos</param>
        /// <param name="e">Argumentos presentados en la ejecución de la carga de datos</param>
        private static void ClientDataSourceLoaded(object sender, LoadedDataEventArgs e)
        {
            if (e.HasError)
            {
                var recurso = LogicStudio.Framework.UI.Utilidades.RecursosLenguaje.Recursos;
                var mensaje = string.Empty;
                mensaje = recurso.GetType().GetProperty("ErrorCarga").GetValue(mensaje, null).ToString();
                VentanaError.Crear(mensaje, e.Error);
                e.MarkErrorAsHandled();
            }
        }
        #endregion

    }

    public class ComandoBuscar : ICommand
    {
        private readonly IObjetoBusqueda _modelo;

        #region Constructor
        public ComandoBuscar(IObjetoBusqueda modelo)
        {
            _modelo = modelo;
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, null);
            }
        }
        #endregion

        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged;

        /// <summary>
        /// Método que se invoca al pulsar el botón buscar o reset
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            var valor = parameter;
            if (valor.ToString().Equals("True"))
            {
                _modelo.AplicarBusqueda();
            }
            if (valor.ToString().Equals("False"))
            {
                _modelo.AplicarReset();
            }

        }
        #endregion
    }
}
